home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK2.toast / Development Kits (Disc 2) / QuickTime Conferencing / Programming Stuff / Sample Code / SeeWorld / Guardian.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-23  |  21.0 KB  |  1,122 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Guardian.c
  3.  
  4.     Contains:    Don't let them slip past…
  5.  
  6.     Written by:    Guy Riddle
  7.  
  8.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. #include <Types.h>
  12. #include <QuickDraw.h>
  13. #include <Fonts.h>
  14. #include <Events.h>
  15. #include <Windows.h>
  16. #include <Menus.h>
  17. #include <Dialogs.h>
  18. #include <Desk.h>
  19. #include <ToolUtils.h>
  20. #include <Memory.h>
  21. #include <SegLoad.h>
  22. #include <Files.h>
  23. #include <Folders.h>
  24. #include <OSUtils.h>
  25. #include <DiskInit.h>
  26. #include <Scrap.h>
  27. #include <Sound.h>
  28. #include <Resources.h>
  29. #include <AppleEvents.h>
  30.  
  31. #include <String.h>
  32. #include <Strings.h>
  33. #include <stdio.h>
  34.  
  35. #include <QuickTimeConferencing.h>
  36.  
  37. #include "See.h"
  38.  
  39. typedef    EventRecord            *EventRecordPtr;
  40. typedef    Byte                *BytePtr;
  41. typedef AppleEvent            *AppleEventPtr;
  42. typedef    Boolean                *BooleanPtr;
  43. typedef    void                *VoidPtr;
  44.  
  45. #define        PW_CLEAR        'pw-C'    
  46. #define        kMTNameType        'mtnm'
  47. #define        kMTNameListType    'mtnl'
  48.  
  49. #define        kCheckInterval    66
  50. #define        kBleepInterval    55
  51.  
  52. #define        kBorderSize        4
  53. #define        kBarHeight        16
  54.  
  55. typedef struct {
  56.     QElemPtr                qLink;
  57.     Rect                    box;
  58.     MTConferenceMember        member;
  59.     MTControllerComponent    controller;
  60.     long                    sizes[5];
  61. #define        kBase              0
  62. #define        kOldest              1
  63. #define        kPrevious          3
  64. #define        kNewest              4
  65.     RgnHandle                border;
  66.     Boolean                    bleeping;
  67. } Member, *MemberPtr;
  68.  
  69.     Boolean                    gQuitNow;
  70.     QHdr                    gMembers;
  71.                             
  72.     MTCString63                gUserName, gPassword;
  73.     
  74.     ComponentInstance        gCC, gBC;
  75.     
  76.     Rect                    gStandardScreen        = { 100, 100, 220, 260 };
  77.     
  78.     SndChannelPtr            gSoundChannel;
  79.     Handle                    gBleepSound;
  80.     long                    gBleepTime, gCheckTime;
  81.     Boolean                    gBleeping;
  82.     MTControllerActionFilterUPP    gGetInOnTheActionUPP;
  83.     MTMediaUPP                gSpyProcUPP;    
  84.     MemberPtr        FindMember(MTConferenceMember);
  85.     MemberPtr        FindMemberWindow(WindowPtr);
  86.     MemberPtr        FindController(MTControllerComponent);
  87.     
  88.     void            Initialize(void);
  89.     void            StartMovieTalk(void);
  90.     pascal OSErr    HandleOAPP(AppleEventPtr, AppleEventPtr, long);
  91.     pascal OSErr    HandleODOC(AppleEventPtr, AppleEventPtr, long);
  92.     void            FileCall(FSSpecPtr);
  93.     pascal OSErr    HandleQUIT(AppleEventPtr, AppleEventPtr, long);
  94.     void            StopMovieTalk(void);
  95.     void            EventLoop(void);
  96.     
  97.     void            DoToolboxEvent(EventRecordPtr);
  98.     void            DoKeyDownEvent(EventRecordPtr);
  99.     void            DoUpdateEvent(EventRecordPtr);
  100.     void            DoMouseDownEvent(EventRecordPtr);
  101.     void            DoDiskEvent(EventRecordPtr);
  102.     void            AdjustMenus(void);
  103.     void            DoMenuBar(long);
  104.     void            DoAppleMenu(short);
  105.     void            DoFileMenu(short);
  106.     void            DoMenuCall(void);
  107.     void            DoMenuHangUp(WindowPtr);
  108.     void            DoMenuSave(int, ResType, WindowPtr);
  109.     void            SaveScreen(WindowPtr);
  110.     
  111.     void            DoConferenceEvent(MTConferenceEventPtr);
  112.     void            DoConfReady(MTConferenceEventPtr);
  113.     void            DoMemberReady(MTConferenceEventPtr);
  114.     pascal Boolean    GetInOnTheAction(MTControllerComponent, MTControllerActionType, VoidPtr, long);
  115.     void            DoMemberTerminated(MTConferenceEventPtr);
  116.     void            DoPhoneRinging(MTConferenceEventPtr);
  117.     void            DoMemberJoining(MTConferenceEventPtr);
  118.     Boolean            Requires(MTConferenceMember, OSType);
  119.     Handle            GetPassword(Ptr);
  120.     void            EnableButton(DialogRef, short, Boolean);
  121.     void            GetValue(BytePtr, DialogRef, short);
  122.     
  123.     pascal OSErr    SpyProc(MTStreamChunkRecordPtr);
  124.     void            IntruderCheck(void);
  125.     Boolean            ShouldBleep(MemberPtr);
  126.     void            BleepAgain(void);
  127.  
  128.     MemberPtr        CallOne(MTNamePtr);
  129.     void            SaveMovie(Handle);
  130.     void            SaveSnapshot(Handle);
  131.     void            Sorry(int, int, MTConferenceMember, OSErr);
  132.     
  133. /*
  134.  *    WeSeeYou
  135.  *
  136.  *    This conferencing application is receive only.  It doesn't accept incoming calls or transmit
  137.  *    any media data.  It is basically a motion detector.
  138.  *
  139.  *    • Required Apple Events are supported (well, not printing)
  140.  *
  141.  *    • You can save a "monitor setting" to a file which can be double-clicked or dragged to WeSeeYou
  142.  *    or placed into your Startup Items folder to automatically call someone
  143.  *
  144.  *    • Windows are auto-positioned to avoid overlap
  145.  *
  146.  *    • An arbitary number of calls can be simultaneously handled at once
  147.  *
  148.  *    • Calls are never merged into multi-party conferences
  149.  *
  150.  *    • A lot of manual labor is expended getting the colored border positioned nicely
  151.  */
  152.  
  153. void main()
  154. {
  155.     Initialize();
  156.     EventLoop();
  157.     StopMovieTalk();
  158. }
  159.  
  160.     void 
  161. Initialize(
  162.     void
  163. ){
  164.     Handle                    menuBar;
  165.  
  166.     InitGraf((Ptr) &qd.thePort);
  167.     InitFonts();
  168.     InitWindows();
  169.     InitMenus();
  170.     TEInit();
  171.     InitDialogs(nil);
  172.     InitCursor();
  173.             
  174.     gSpyProcUPP = NewMTMediaProc(SpyProc);    
  175.     StartMovieTalk();
  176.  
  177.     menuBar = GetNewMBar(rGuardianMenuBar);
  178.  
  179.     SetMenuBar(menuBar);
  180.     DisposHandle(menuBar);
  181.     AddResMenu(GetMHandle(mApple), 'DRVR');
  182.  
  183.     DrawMenuBar();
  184.     
  185.     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(HandleOAPP), 0, false);
  186.     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(HandleODOC), 0, false);
  187.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(HandleQUIT), 0, false);
  188.     
  189.     SndNewChannel(&gSoundChannel, sampledSynth, initMono, 0);
  190.     gBleepSound = GetResource('snd ', rBleepSound);
  191.     HLockHi(gBleepSound);
  192. }
  193.  
  194.     void
  195. StartMovieTalk(
  196.     void
  197. ){
  198.     StringHandle            sh;
  199.  
  200.     sh = GetString(kMTAppleTalkUserName);
  201.     
  202.     strncpy((char*)gUserName, (char*)*sh+1, **sh);
  203.     
  204.     gCC = OpenDefaultComponent(kMTConferenceType, kMTMovieTalkSubType);
  205.     
  206.     MTConferenceSetMode(gCC, mtReceiveMediaModeMask);
  207.     MTConferenceSetDefaultWindowProcID(gCC, zoomDocProc);
  208.     
  209.     MTConferenceListen(gCC, gUserName, gUserName, (MTCString)"mtlkatlk\tNoIncomingCalls\x0Dmtlktcpi\t606\x0Dmtlkisdn\t-\x0D");
  210.     
  211.     gGetInOnTheActionUPP = NewMTControllerActionFilterProc(GetInOnTheAction);
  212.     MTConferenceSetDefaultActionFilter(gCC, gGetInOnTheActionUPP, 0);
  213.     
  214.     gBC = OpenDefaultComponent(kMTBrowserType, kMTAppleTalkSubType);
  215. }
  216.  
  217.     pascal OSErr
  218. HandleOAPP(
  219.     AppleEventPtr            /* unused */,
  220.     AppleEventPtr            /* unused */,
  221.     long                    /* unused */
  222. ){
  223.     return(noErr);
  224. }
  225.  
  226.     pascal OSErr
  227. HandleODOC(
  228.     AppleEventPtr            aev,
  229.     AppleEventPtr            /* unused */,
  230.     long                    /* unused */
  231. ){
  232.     AEDescList                docs;
  233.     long                    n, count;
  234.     AEKeyword                key;
  235.     FSSpec                    fss;
  236.     DescType                type;
  237.     Size                    size;
  238.     OSErr                    err;
  239.     
  240.     if(err = AEGetParamDesc(aev, keyDirectObject, typeAEList, &docs))
  241.         return(err);
  242.         
  243.     AECountItems(&docs, &count);
  244.     
  245.     for(n = 1; n <= count; n++)
  246.         if(err = AEGetNthPtr(&docs, n, typeFSS, &key, &type, &fss, sizeof(FSSpec), &size))
  247.             break;
  248.         else
  249.             FileCall(&fss);
  250.             
  251.     AEDisposeDesc(&docs);
  252.     
  253.     return(err);
  254. }
  255.  
  256.     void
  257. FileCall(
  258.     FSSpecPtr                fs
  259. ){
  260.     int                        n, count;
  261.     Handle                    h;
  262.     MemberPtr                mp;
  263.     short                    id, refnum;
  264.     ResType                    type;
  265.     Str255                    name;
  266.     
  267.     if(!(refnum = FSpOpenResFile(fs, fsRdPerm)))
  268.         return;
  269.         
  270.     count = Count1Resources(kMTNameType);
  271.     
  272.     for(n = 1; n <= count; n++){
  273.         h = Get1IndResource(kMTNameType, n);
  274.         HLock(h);
  275.         
  276.         mp = CallOne((MTNamePtr) *h);
  277.         
  278.         GetResInfo(h, &id, &type, name);
  279.         
  280.         if(h = Get1Resource('RECT', id))
  281.             mp->box = *(RectPtr) (*h);
  282.     }
  283.     
  284.     CloseResFile(refnum);
  285. }
  286.  
  287.     pascal OSErr
  288. HandleQUIT(
  289.     AppleEventPtr            /* unused */,
  290.     AppleEventPtr            /* unused */,
  291.     long                    /* unused */
  292. ){
  293.     gQuitNow = true;
  294.     
  295.     return(noErr);
  296. }
  297.  
  298.     void
  299. EventLoop(
  300.     void
  301. ){
  302.     EventRecord                tEvent;
  303.     MTConferenceEvent        cEvent;
  304.  
  305.     for(; !gQuitNow;){
  306.         if(MTConferenceGetNextEvent(gCC, &cEvent))
  307.             DoConferenceEvent(&cEvent);
  308.             
  309.         if(WaitNextEvent(everyEvent, &tEvent, 1, 0))
  310.             DoToolboxEvent(&tEvent);
  311.             
  312.         IntruderCheck();
  313.         BleepAgain();
  314.     }
  315. }
  316.  
  317.     void
  318. IntruderCheck(
  319.     void
  320. ){
  321.     MemberPtr                mp;
  322.     long                    now;
  323.     Boolean                    bleep;
  324.     
  325.     now = TickCount();
  326.     
  327.     if(gCheckTime > now)
  328.         return;
  329.     gCheckTime = now + kCheckInterval;
  330.  
  331.     bleep = false;
  332.     
  333.     for(mp = (MemberPtr) gMembers.qHead; mp; mp = (MemberPtr) mp->qLink)
  334.         if(ShouldBleep(mp))
  335.             bleep = true;
  336.             
  337.     if(bleep == gBleeping)
  338.         return;
  339.     gBleeping = bleep;
  340.  
  341.     for(mp = (MemberPtr) gMembers.qHead; mp; mp = (MemberPtr) mp->qLink){
  342.         SetPort((GrafPtr) MTControllerGetControllerPort(mp->controller));
  343.         InvalRgn(mp->border);
  344.     }
  345. }
  346.  
  347.     Boolean
  348. ShouldBleep(
  349.     MemberPtr                mp
  350. ){
  351.     long                    on, off;
  352.     int                        i;
  353.     
  354.     if(mp->sizes[kNewest] == 0){
  355.         mp->bleeping = false;
  356.         
  357.         for(i = kNewest; i >= 0; i--)
  358.             mp->sizes[i] = 0;
  359.     }else if(mp->sizes[kBase]){
  360.         on = (mp->sizes[kBase] * 150) / 100;
  361.         off = mp->sizes[kBase];
  362.         
  363.         if(mp->sizes[kNewest] > on)
  364.             mp->bleeping = true;
  365.         else if(mp->sizes[kNewest] < off && mp->sizes[kPrevious] < off)
  366.             mp->bleeping = false;
  367.             
  368.         if(mp->sizes[kOldest] > mp->sizes[kBase])
  369.             mp->sizes[kBase] = ((3 * mp->sizes[kBase]) + mp->sizes[kOldest]) / 4;
  370.         else
  371.             mp->sizes[kBase] = (mp->sizes[kBase] + (3 * mp->sizes[kOldest])) / 4;
  372.     }else
  373.         mp->sizes[kBase] = mp->sizes[kOldest];
  374.  
  375.     for(i = kOldest; i <= kPrevious; i++)
  376.         mp->sizes[i] = mp->sizes[i+1];
  377.     mp->sizes[kNewest] = 0;
  378.         
  379.     return(mp->bleeping);
  380. }
  381.  
  382.     void
  383. BleepAgain(
  384.     void
  385. ){
  386.     long                    now;
  387.     
  388.     if(!gBleeping)
  389.         return;
  390.     
  391.     now = TickCount();
  392.     
  393.     if(gBleepTime > now)
  394.         return;
  395.     gBleepTime = now + kBleepInterval;
  396.     
  397.     SndPlay(gSoundChannel, (SndListHandle)gBleepSound, true);
  398. }
  399.  
  400.     void
  401. DoToolboxEvent(
  402.     EventRecordPtr            ev
  403. ){
  404.     switch(ev->what) {
  405.     case mouseDown:
  406.         DoMouseDownEvent(ev);
  407.         break;
  408.     
  409.     case keyDown:
  410.         DoKeyDownEvent(ev);
  411.         break;
  412.         
  413.     case kHighLevelEvent:
  414.         AEProcessAppleEvent(ev);
  415.         break;
  416.         
  417.     case updateEvt:
  418.         DoUpdateEvent(ev);
  419.         break;
  420.     
  421.     case diskEvt:
  422.         DoDiskEvent(ev);
  423.     }
  424. }
  425.  
  426.     void
  427. DoMouseDownEvent(
  428.     EventRecordPtr            ev
  429. ){
  430.     WindowPtr                wp;
  431.     short                    part;
  432.     
  433.     part = FindWindow(ev->where, &wp);
  434.     
  435.     switch(part){
  436.     case inMenuBar:
  437.         AdjustMenus();
  438.         DoMenuBar(MenuSelect(ev->where));
  439.     }
  440. }
  441.  
  442.     void
  443. DoKeyDownEvent(
  444.     EventRecordPtr            ev
  445. ){
  446.     if(ev->modifiers & cmdKey){
  447.         AdjustMenus();    
  448.         DoMenuBar(MenuKey(ev->message & charCodeMask));
  449.     }
  450. }
  451.  
  452.     void
  453. DoUpdateEvent(
  454.     EventRecordPtr            ev
  455. ){
  456.     MemberPtr                mp;
  457.     WindowPtr                wp;
  458.     
  459.     wp = (WindowPtr) ev->message;
  460.     SetPort(wp);
  461.     
  462.     BeginUpdate(wp);
  463.     
  464.     if(mp = FindMemberWindow(wp)){
  465.         BackColor(mp->bleeping ? redColor : greenColor);
  466.         EraseRgn(mp->border);
  467.         BackColor(whiteColor);
  468.     }
  469.     
  470.     EndUpdate(wp);
  471. }
  472.  
  473.     void
  474. DoDiskEvent(
  475.     EventRecordPtr            ev
  476. ){
  477.     Point                    where;
  478.  
  479.     if(HiWord(ev->message)){
  480.         SetPt(&where, kDILeft, kDITop);
  481.         DIBadMount(where, ev->message);
  482.     }
  483. }
  484.  
  485.     void
  486. AdjustMenus(
  487.     void
  488. ){
  489.     MenuHandle                mh;
  490.     
  491.     mh = GetMHandle(mtFile);
  492.     
  493.     if(FrontWindow()){
  494.         EnableItem(mh, itClose);
  495.         EnableItem(mh, itSave);
  496.         EnableItem(mh, itSaveAll);
  497.     }else{
  498.         DisableItem(mh, itClose);
  499.         DisableItem(mh, itSave);
  500.         DisableItem(mh, itSaveAll);
  501.     }
  502. }
  503.  
  504.     void
  505. DoMenuBar(
  506.     long                    selection
  507. ){
  508.     short                    menuID;    
  509.     short                    menuItem;
  510.  
  511.     menuID = HiWord(selection);
  512.     menuItem = LoWord(selection);
  513.     
  514.     switch(menuID){
  515.     case mApple:
  516.         DoAppleMenu(menuItem);
  517.         break;
  518.         
  519.     case mtFile:
  520.         DoFileMenu(menuItem);
  521.         break;
  522.         
  523.     case mEdit:                    /* call SystemEdit for DA editing & MultiFinder */
  524.         SystemEdit(menuItem-1);
  525.     }
  526.     
  527.     HiliteMenu(0);
  528. }
  529.  
  530.     void
  531. DoAppleMenu(
  532.     short                    item
  533. ){
  534.     DialogRef                dp;
  535.     Str255                    daName;
  536.     short                    itemHit;
  537.  
  538.     switch(item){
  539.     case iAbout:
  540.         dp = GetNewDialog(rAboutAlert, nil, (WindowRef) -1);
  541.         SetDialogDefaultItem(dp, 1);
  542.         
  543.         ModalDialog(0, &itemHit);
  544.         
  545.         DisposeDialog(dp);
  546.         break;
  547.         
  548.     default:            /* all non-About items in this menu are DAs */
  549.         GetItem(GetMHandle(mApple), item, daName);
  550.         OpenDeskAcc(daName);
  551.     }
  552. }
  553.  
  554.     void
  555. DoFileMenu(
  556.     short                    item
  557. ){
  558.     switch(item){
  559.     case itNew:
  560.         DoMenuCall();
  561.         break;
  562.     
  563.     case itClose:
  564.         DoMenuHangUp(FrontWindow());
  565.         break;
  566.         
  567.     case itSave:
  568.         DoMenuSave(1, kMTNameType, FrontWindow());
  569.         break;
  570.         
  571.     case itSaveAll:
  572.         DoMenuSave(2, kMTNameListType, 0);
  573.         break;
  574.         
  575.     case itQuit:
  576.         gQuitNow = true;
  577.     }
  578. }
  579.  
  580.     void
  581. StopMovieTalk(
  582.     void
  583. ){
  584.     CloseComponent(gCC);
  585.     CloseComponent(gBC);
  586. }
  587.  
  588.     void
  589. DoMenuCall(
  590.     void
  591. ){
  592.     MTNameListPtr            names;
  593.     MTNamePtr                np;
  594.     int                        count;
  595.     ComponentResult            err;
  596.     
  597.     err = MTBrowserBrowse(gBC, 0, "\pLets Monitor…", (MTCString)"mtlkatlk\tMulticaster\x0D", 0, &names);
  598.     
  599.     if(err)
  600.         return;
  601.         
  602.     count = GetMTNameListCount(names);
  603.     np = &(names->list[0]);
  604.  
  605.     while(--count >= 0)
  606.         CallOne(np++);
  607.         
  608.     DisposeMTNameList(names);
  609. }
  610.  
  611.     MemberPtr
  612. CallOne(
  613.     MTNamePtr                np
  614. ){
  615.     MemberPtr                mp;
  616.     
  617.     if(!(mp = FindMember(0)))
  618.         return(0);
  619.  
  620.     mp->member = MTConferenceCall(gCC, (MTCString)"Security Central", np);
  621.     mp->box = gStandardScreen;
  622.     
  623.     return(mp);
  624. }
  625.  
  626.     void
  627. DoMenuHangUp(
  628.     WindowPtr                wp
  629. ){
  630.     MemberPtr                mp;
  631.     
  632.     if(mp = FindMemberWindow(wp))
  633.         MTConferenceTerminate(gCC, MTConferenceGetMemberConference(gCC, mp->member));
  634. }
  635.  
  636.     void
  637. DoMenuSave(
  638.     int                        note,
  639.     ResType                    filetype,
  640.     WindowPtr                wp
  641. ){
  642.     Handle                    h;
  643.     short                    refnum;
  644.     StandardFileReply        reply;
  645.     Str255                    prompt, name;
  646.     
  647.     GetIndString(prompt, 401, note);
  648.     
  649.     if(wp)
  650.         GetWTitle(wp, name);
  651.     else
  652.         GetIndString(name, 402, note);
  653.         
  654.     StandardPutFile(prompt, name, &reply);
  655.     
  656.     if(!reply.sfGood)
  657.         return;
  658.         
  659.     if(reply.sfReplacing)
  660.         FSpDelete(&reply.sfFile);
  661.         
  662.     FSpCreateResFile(&reply.sfFile, 'SW•7', filetype, reply.sfScript);
  663.     if(!(refnum = FSpOpenResFile(&reply.sfFile, fsRdWrPerm)))
  664.         return;
  665.     
  666.     if(wp)
  667.         SaveScreen(wp);
  668.     else
  669.         for(wp = FrontWindow(); wp; wp = (WindowPtr) ((WindowPeek) wp)->nextWindow)
  670.             SaveScreen(wp);
  671.             
  672.     h = GetResource('STR ', -16396);
  673.     DetachResource(h);
  674.     AddResource(h, 'STR ', -16396, "\p");
  675.     
  676.     CloseResFile(refnum);
  677. }
  678.  
  679.     void
  680. SaveScreen(
  681.     WindowPtr                wp
  682. ){
  683.     MTNameListPtr            nl;
  684.     MemberPtr                mp;
  685.     Handle                    h;
  686.     short                    id;
  687.     Rect                    box;
  688.     
  689.     if(!(mp = FindMemberWindow(wp)))
  690.         return;
  691.         
  692.     nl = MTConferenceGetReturnAddress(gCC, mp->member);
  693.     PtrToHand((Ptr) nl->list, &h, sizeof(MTName));
  694.     DisposeMTNameList(nl);
  695.     
  696.     id = UniqueID(kMTNameType);
  697.     
  698.     AddResource(h, kMTNameType, id, "\p");
  699.     
  700.     SetPort(wp);
  701.     box = wp->portRect;
  702.     LocalToGlobal((PointPtr) &box.top);
  703.     LocalToGlobal((PointPtr) &box.bottom);
  704.     box.bottom -= 16;
  705.     
  706.     PtrToHand((Ptr) &box, &h, sizeof(Rect));
  707.     AddResource(h, 'RECT', id, "\p");
  708. }
  709.  
  710.     void
  711. DoConferenceEvent(
  712.     MTConferenceEventPtr    ce
  713. ){
  714.     switch(ce->what){
  715.     case mtConferenceReadyEvent:
  716.         DoConfReady(ce);
  717.         break;
  718.     
  719.     case mtMemberReadyEvent:
  720.         DoMemberReady(ce);
  721.         break;
  722.     
  723.     case mtMemberTerminatedEvent:
  724.         DoMemberTerminated(ce);
  725.         break;
  726.     
  727.     case mtMemberJoiningEvent:
  728.         DoMemberJoining(ce);
  729.         break;
  730.         
  731.     case mtPhoneRingingEvent:
  732.         DoPhoneRinging(ce);
  733.         break;
  734.     
  735.     case mtRefusedEvent:
  736.         Sorry(701, 1, ce->who, ce->err);
  737.         break;
  738.     
  739.     case mtFailedEvent:
  740.         Sorry(701, 2, ce->who, ce->err);
  741.         break;
  742.         
  743.     case mtSnapshotTakenEvent:
  744.         SaveSnapshot(ce->surprise);
  745.         break;
  746.         
  747.     case mtMovieRecordedEvent:
  748.         SaveMovie(ce->surprise);
  749.     }
  750.     
  751.     if(ce->surprise)
  752.         DisposeHandle(ce->surprise);
  753. }
  754.  
  755.     void
  756. DoMemberJoining(
  757.     MTConferenceEventPtr    ce
  758. ){
  759.     MemberPtr                mp;
  760.     
  761.     if(mp = FindMember(0))
  762.         mp->member = ce->who;
  763.     else
  764.         Sorry(702, 2, ce->who, 0);
  765. }
  766.  
  767.     void
  768. DoConfReady(
  769.     MTConferenceEventPtr    ce
  770. ){
  771.     MTConferenceActivateConference(gCC, ce->who, 0);
  772. }
  773.  
  774.     void
  775. DoMemberReady(
  776.     MTConferenceEventPtr    ce
  777. ){
  778.     MemberPtr                mp;
  779.     MTControllerComponent    mtc;
  780.     
  781.     
  782.     if(ce->bonus & mtReceiveMediaModeMask){    
  783.         if(!(mp = FindMember(ce->who)))
  784.             return;
  785.     
  786.         mtc = MTConferenceNewPreparedController(gCC, &mp->box,
  787.                mtAutoPositionPrepMask+mtAuxiliaryClosePrepMask+mtWindowVisiblePrepMask+mtControllerVisiblePrepMask+mtEnableSnapshotPrepMask+mtEnableRecordPrepMask,
  788.                MTConferenceGetMemberName(gCC, mp->member));
  789.         MTControllerSetControllerAttached(mtc, false);
  790.                
  791.         mp->controller = mtc;
  792.         
  793.         MTDirectorSetRecordProc(MTControllerGetStreamDirector(mtc), gSpyProcUPP, (long) mp);
  794.     }else
  795.         mtc = 0;
  796.                        
  797.     MTConferenceActivateMember(gCC, ce->who, mtc);
  798. }
  799.  
  800.     pascal OSErr
  801. SpyProc(
  802.     MTStreamChunkRecordPtr    chunk
  803. ){
  804.     MemberPtr                mp;
  805.  
  806.     if(chunk->chunkError || chunk->chunkPriority != mtChunkPriorityVideo)
  807.         return(noErr);
  808.         
  809.     mp = (MemberPtr) chunk->chunkRefCon;
  810.     
  811.     if(chunk->chunkSize > mp->sizes[kNewest])
  812.         mp->sizes[kNewest] = chunk->chunkSize;
  813.         
  814.     return(noErr);
  815. }
  816.  
  817.     pascal Boolean
  818. GetInOnTheAction(
  819.     MTControllerComponent    mtc,
  820.     MTControllerActionType    action,
  821.     VoidPtr                    params,
  822.     long                    /* unused */
  823. ){
  824.     MemberPtr                mp;
  825.     WindowPtr                wp;
  826.     MTDirectorComponent        sd;
  827.     RgnHandle                rh;
  828.     Rect                    old, new, box;
  829.     MatrixRecord            trix;
  830.     
  831.     if((action != mtControllerActionControllerSizeChanged) || !(mp = FindController(mtc)))
  832.         return(false);
  833.         
  834.     if(*(BooleanPtr)params)
  835.         MTControllerGetControllerBoundsRect(mtc, &old);
  836.     else{
  837.         rh = MTControllerGetControllerBoundsRgn(mtc);
  838.         old = (*rh)->rgnBBox;
  839.         InsetRect(&old, kBorderSize, kBorderSize);
  840.         OffsetRect(&old, -kBorderSize, -kBorderSize);
  841.         DisposeRgn(rh);
  842.     }
  843.     old.bottom -= kBarHeight;
  844.     
  845.     sd = MTControllerGetStreamDirector(mtc);
  846.     
  847.     MTDirectorChangedStreamFormats(sd, false);
  848.  
  849.     new = old;
  850.     OffsetRect(&new, kBorderSize, kBorderSize);
  851.     SetRect(&box, 0, new.bottom+kBorderSize, new.right+kBorderSize, new.bottom+kBorderSize+kBarHeight);
  852.     
  853.     MTControllerPositionController(mtc, &new, &box, 0);
  854.     wp = (WindowPtr) MTControllerGetControllerPort(mtc);
  855.     SizeWindow(wp, box.right, box.bottom, true);
  856.  
  857.     MTDirectorGetRect(sd, kMTAllStreams, &old);
  858.     RectMatrix(&trix, &old, &new);
  859.     MTDirectorSetMatrix(sd, kMTAllStreams, &trix);
  860.     
  861.     MTDirectorChangedStreamFormats(sd, true);
  862.     
  863.     mp->box = new;
  864.     InsetRect(&new, -kBorderSize, -kBorderSize);
  865.     RectRgn(mp->border, &new);
  866.     rh = NewRgn();
  867.     RectRgn(rh, &mp->box);
  868.     XorRgn(rh, mp->border, mp->border);
  869.     DisposeRgn(rh);
  870.     SetPort(wp);
  871.     InvalRgn(mp->border);
  872.  
  873.     return(true);
  874. }
  875.  
  876.     void
  877. DoMemberTerminated(
  878.     MTConferenceEventPtr    ce
  879. ){
  880.     MemberPtr                mp;
  881.     
  882.     if(!(mp = FindMember(ce->who)))
  883.         return;
  884.         
  885.     if(mp->controller)
  886.         MTConferenceDisposeController(gCC, mp->controller);
  887.         
  888.     Dequeue((QElemPtr) mp, &gMembers);
  889.     DisposeRgn(mp->border);
  890.     DisposePtr((Ptr) mp);
  891. }
  892.  
  893.     void
  894. DoPhoneRinging(
  895.     MTConferenceEventPtr    ce
  896. ){
  897.     Handle                    ph;
  898.     
  899.     if((ce->bonus & mtRequiredMessagesModeMask) && Requires(ce->who, PW_CLEAR) && (ph = GetPassword((Ptr)MTConferenceGetMemberName(gCC, ce->who))))
  900.         MTConferenceSendMessageToMember(gCC, ce->who, ph, PW_CLEAR, 1);
  901. }
  902.  
  903.     Boolean
  904. Requires(
  905.     MTConferenceMember        who,
  906.     OSType                    type
  907. ){
  908.     MTCapabilitiesHandle    ch;
  909.     MTCapabilitiesPtr        cp;
  910.     int                        n;
  911.     
  912.     ch = MTConferenceGetMemberMessageCapabilities(gCC, who);
  913.     
  914.     for(n = (*ch)->count, cp = (*ch)->capability; --n >= 0; cp++)
  915.         if(type == cp->messageType && cp->desires == mtMessageRequiredCapability){
  916.             DisposeHandle((Handle) ch);
  917.             return(true);
  918.         }
  919.     
  920.     DisposeHandle((Handle) ch);
  921.     return(false);
  922. }
  923.  
  924.     Handle
  925. GetPassword(
  926.     Ptr                        name
  927. ){
  928.     DialogRef                dp;
  929.     short                    itemHit;
  930.     Handle                    ph;
  931.     Str255                    p1;
  932.     
  933.     if(AEInteractWithUser(20*60, 0, 0))
  934.         return(0);
  935.     
  936.     ParamText(nil, c2pstr(strcpy((char*)p1, name)), nil, nil);
  937.     gPassword[0] = 0;
  938.     
  939.     dp = GetNewDialog(rPassword, 0, (WindowRef) -1);
  940.     SetDialogDefaultItem(dp, diOK);
  941.     SetDialogCancelItem(dp, diCancel);
  942.     SetDialogTracksCursor(dp, true);
  943.     PostEvent(keyDown, '\b');        // ick
  944.     
  945.     do{
  946.         EnableButton(dp, diOK, gPassword[0]);
  947.         
  948.         ModalDialog(0, &itemHit);
  949.         
  950.         GetValue(gPassword, dp, diPassword);
  951.     }while(itemHit > diCancel);
  952.     
  953.     DisposeDialog(dp);
  954.     InitCursor();
  955.     
  956.     if(itemHit == diCancel)
  957.         return(0);
  958.     
  959.     PtrToHand(gPassword, &ph, strlen((char*)gPassword)+1);
  960.     
  961.     return(ph);
  962. }
  963.  
  964.     void
  965. EnableButton(
  966.     DialogRef                dp,
  967.     short                    item,
  968.     Boolean                    enabled
  969. ){
  970.     Handle                    ih;
  971.     Rect                    rect;
  972.     short                    type;
  973.     
  974.     GetDialogItem(dp, item, &type, &ih, &rect);
  975.     
  976.     if(enabled)
  977.         type &= ~itemDisable;
  978.     else
  979.         type |= itemDisable;
  980.         
  981.     HiliteControl((ControlHandle) ih, enabled ? 0 : 255);
  982.     
  983.     SetDialogItem(dp, item, type, ih, &rect);
  984.     
  985.     SetPort(dp);
  986.     InsetRect(&rect, -5, -5);
  987.     InvalRect(&rect);
  988. }
  989.  
  990.     void
  991. GetValue(
  992.     BytePtr                    p,
  993.     DialogRef                dp,
  994.     short                    item
  995. ){
  996.     Handle                    ih;
  997.     Rect                    rect;
  998.     short                    type;
  999.     
  1000.     GetDialogItem(dp, item, &type, &ih, &rect);
  1001.     GetDialogItemText(ih, p);
  1002.     
  1003.     if(p[0] && p[p[0]] < ' '){
  1004.         p[0]--;            // strip CR or other junk
  1005.         SetDialogItemText(ih, p);
  1006.     }
  1007.     
  1008.     p2cstr(p);
  1009. }
  1010.  
  1011.     void
  1012. SaveSnapshot(
  1013.     Handle                    pic
  1014. ){
  1015.     ZeroScrap();
  1016.     
  1017.     HLock(pic);
  1018.     
  1019.     PutScrap(GetHandleSize(pic), 'PICT', *pic);
  1020. }
  1021.  
  1022.     void
  1023. SaveMovie(
  1024.     Handle                    h
  1025. ){
  1026.     Ptr                        p;
  1027.     int                        i;
  1028.     long                    dirid;
  1029.     short                    vrefnum;
  1030.     FSSpecPtr                temp;
  1031.     FSSpec                    spec;
  1032.     Str255                    newname;
  1033.     
  1034.     HLock(h);
  1035.     temp =(FSSpecPtr) *h;
  1036.     
  1037.     FindFolder(kOnSystemDisk, kDesktopFolderType, true, &vrefnum, &dirid);
  1038.     FSMakeFSSpec(vrefnum, dirid, "\p", &spec);
  1039.     FSpCatMove(temp, &spec);        // move it to the desktop
  1040.     
  1041.     FSMakeFSSpec(vrefnum, dirid, temp->name, &spec);
  1042.     GetIndString(newname, rWildSTRs, srMovieName);
  1043.     p = strchr((char*)newname, '?');
  1044.     
  1045.     for(i = 1; i < 10; i++){
  1046.         *p = '0'+i;
  1047.         
  1048.         if(FSpRename(&spec, newname) == noErr)
  1049.             return;                    // and give it a better name
  1050.     }
  1051.     
  1052.     SysBeep(1);
  1053. }
  1054.     
  1055.     MemberPtr
  1056. FindMember(
  1057.     MTConferenceMember        who
  1058. ){
  1059.     MemberPtr                mp;
  1060.  
  1061.     if(who){
  1062.         for(mp = (MemberPtr) gMembers.qHead; mp; mp = (MemberPtr) mp->qLink)
  1063.             if(who == mp->member)
  1064.                 return(mp);
  1065.     }else if(mp = (MemberPtr) NewPtrClear(sizeof(Member))){
  1066.         Enqueue((QElemPtr) mp, &gMembers);
  1067.         mp->border = NewRgn();
  1068.     }
  1069.         
  1070.     return(mp);
  1071. }
  1072.     
  1073.     MemberPtr
  1074. FindMemberWindow(
  1075.     WindowPtr                wp
  1076. ){
  1077.     MemberPtr                mp;
  1078.     MTControllerComponent    mtc;
  1079.     
  1080.     mtc = (MTControllerComponent) GetWRefCon(wp);
  1081.  
  1082.     for(mp = (MemberPtr) gMembers.qHead; mp; mp = (MemberPtr) mp->qLink)
  1083.         if(mtc == mp->controller)
  1084.             break;
  1085.         
  1086.     return(mp);
  1087. }
  1088.     
  1089.     MemberPtr
  1090. FindController(
  1091.     MTControllerComponent    mtc
  1092. ){
  1093.     MemberPtr                mp;
  1094.  
  1095.     for(mp = (MemberPtr) gMembers.qHead; mp; mp = (MemberPtr) mp->qLink)
  1096.         if(mtc == mp->controller)
  1097.             break;
  1098.         
  1099.     return(mp);
  1100. }
  1101.  
  1102.     void
  1103. Sorry(
  1104.     int                        why,
  1105.     int                        note,
  1106.     MTConferenceMember        who,
  1107.     OSErr                    err
  1108. ){
  1109.     Str255                    p1, p2, p3;
  1110.     
  1111.     if(AEInteractWithUser(20*60, 0, 0))
  1112.         return;
  1113.     
  1114.     GetIndString(p1, why, note);
  1115.     
  1116.     strcpy((char*)p2, (char*)MTConferenceGetMemberName(gCC, who));
  1117.     sprintf((char*)p3, "%d", err);
  1118.     
  1119.     ParamText(nil, p1, c2pstr((char*)p2), c2pstr((char*)p3));
  1120.     
  1121.     CautionAlert(why, 0);
  1122. }